// TextLineDetector.cpp 修复 OpenMP 循环问题
#include "TextLineDetector.h"
#include <hilog/log.h>
#include <algorithm>
#include <cmath>

#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x3201
#define LOG_TAG "TextLineDetector"

using Params = TextLineDetector::OptimizedParams;

// SamplingInfo 构造函数：预计算所有采样参数
TextLineDetector::SamplingInfo::SamplingInfo(int width, int height, const Rectangle& region, bool forFrequency) {
    // 确定有效区域
    if (region.width > 0 && region.height > 0) {
        startX = region.x;
        startY = region.y;
        effectiveWidth = region.width;
        effectiveHeight = region.height;
    } else {
        startX = startY = 0;
        effectiveWidth = width;
        effectiveHeight = height;
    }
    
    // 预计算采样步长
    if (forFrequency) {
        int totalPixels = effectiveWidth * effectiveHeight;
        int sampleStep = std::max(50, totalPixels / Params::MAX_FREQUENCY_SAMPLES);
        rowStep = sampleStep / effectiveWidth + 1;
        colStep = sampleStep % effectiveWidth + 1;
        sampleRows = effectiveHeight / rowStep;
        sampleCols = effectiveWidth / colStep;
    } else {
        sampleRows = std::min(Params::MAX_SAMPLE_ROWS, effectiveHeight);
        sampleCols = std::min(Params::MAX_SAMPLE_COLS, effectiveWidth);
        rowStep = std::max(1, effectiveHeight / sampleRows);
        colStep = std::max(1, effectiveWidth / sampleCols);
    }
    
    // 判断是否使用并行处理
    useParallel = (effectiveWidth * effectiveHeight) >= Params::MIN_PIXELS_FOR_PARALLEL;
}

std::vector<int> TextLineDetector::extractEdgeProfileDirect(const uint8_t* pixelData, int width, int height, 
                                                           int bytesPerPixel, const SamplingInfo& sampling) {
    std::vector<int> edgeProfile;
    edgeProfile.reserve(sampling.sampleRows);
    
    const int threshold = Params::GRAY_THRESHOLD_SQUARED;
    const int maxY = sampling.startY + sampling.effectiveHeight;
    const int maxX = sampling.startX + sampling.effectiveWidth;
    
    if (sampling.useParallel) {
        // 并行处理版本 - 修复 OpenMP 循环条件
        std::vector<int> tempProfile(sampling.sampleRows, 0);
        
        #pragma omp parallel for
        for (int i = 0; i < sampling.sampleRows; ++i) {
            int y = sampling.startY + i * sampling.rowStep;
            if (y >= maxY) continue;
            
            int edgeCount = 0;
            uint8_t prevR, prevG, prevB;
            uint8_t currR, currG, currB;
            
            // 获取第一个像素
            getPixelDirect(pixelData, sampling.startX, y, width, bytesPerPixel, prevR, prevG, prevB);
            int prevGray = getGrayValue(prevR, prevG, prevB);
            
            for (int x = sampling.startX + sampling.colStep; x < maxX; x += sampling.colStep) {
                getPixelDirect(pixelData, x, y, width, bytesPerPixel, currR, currG, currB);
                int currGray = getGrayValue(currR, currG, currB);
                
                int grayDiff = currGray - prevGray;
                if (grayDiff * grayDiff > threshold) {
                    edgeCount++;
                }
                
                prevGray = currGray;
            }
            
            tempProfile[i] = edgeCount;
        }
        
        edgeProfile = std::move(tempProfile);
    } else {
        // 串行处理版本（小数据集）
        for (int y = sampling.startY; y < maxY; y += sampling.rowStep) {
            int edgeCount = 0;
            uint8_t prevR, prevG, prevB;
            uint8_t currR, currG, currB;
            
            getPixelDirect(pixelData, sampling.startX, y, width, bytesPerPixel, prevR, prevG, prevB);
            int prevGray = getGrayValue(prevR, prevG, prevB);
            
            for (int x = sampling.startX + sampling.colStep; x < maxX; x += sampling.colStep) {
                getPixelDirect(pixelData, x, y, width, bytesPerPixel, currR, currG, currB);
                int currGray = getGrayValue(currR, currG, currB);
                
                int grayDiff = currGray - prevGray;
                if (grayDiff * grayDiff > threshold) {
                    edgeCount++;
                }
                
                prevGray = currGray;
            }
            
            edgeProfile.push_back(edgeCount);
        }
    }
    
    return edgeProfile;
}

bool TextLineDetector::analyzeTextLinePatternOptimized(const std::vector<int>& edgeProfile, 
                                                      const SamplingInfo& sampling) {
    if (edgeProfile.empty() || sampling.sampleRows <= 5) {
        return false;
    }
    
    const int threshold = std::max(Params::EDGE_THRESHOLD_BASE, 
                                  sampling.effectiveWidth / Params::EDGE_THRESHOLD_DIVISOR);
    
    int textLines = 0;
    int emptyLines = 0;
    int totalTextRows = 0;
    bool inTextRegion = false;
    int consecutiveTextLines = 0;
    
    // 优化的循环：减少条件判断
    for (size_t i = 0; i < edgeProfile.size(); ++i) {
        bool hasEdges = edgeProfile[i] > threshold;
        
        if (hasEdges) {
            totalTextRows++;
            if (inTextRegion) {
                consecutiveTextLines++;
            } else {
                inTextRegion = true;
                consecutiveTextLines = 1;
            }
        } else {
            if (inTextRegion && consecutiveTextLines >= Params::MIN_CONSECUTIVE_LINES) {
                textLines++;
            }
            inTextRegion = false;
            consecutiveTextLines = 0;
            emptyLines++;
        }
    }
    
    // 处理最后一个文本块
    if (inTextRegion && consecutiveTextLines >= Params::MIN_CONSECUTIVE_LINES) {
        textLines++;
    }
    
    // 使用整数运算避免浮点
    int emptyRatioPercent = (emptyLines * 100) / static_cast<int>(edgeProfile.size());
    int textRowRatioPercent = (totalTextRows * 100) / static_cast<int>(edgeProfile.size());
    
    bool hasText = textLines >= Params::MIN_TEXT_BLOCKS || 
                   (totalTextRows > 0 && emptyRatioPercent >= Params::MIN_EMPTY_RATIO_PERCENT) ||
                   textRowRatioPercent > Params::MIN_TEXT_ROW_RATIO_PERCENT;
    
    return hasText;
}

bool TextLineDetector::analyzeColorFrequencyDirect(const uint8_t* pixelData, int width, int height, 
                                                   int bytesPerPixel, const SamplingInfo& sampling) {
    int colorBuckets[Params::COLOR_BUCKET_COUNT] = {0};
    int validSamples = 0;
    const int maxSamples = Params::MAX_FREQUENCY_SAMPLES;
    
    const int maxY = sampling.startY + sampling.effectiveHeight;
    const int maxX = sampling.startX + sampling.effectiveWidth;
    
    if (sampling.useParallel) {
        // 并行版本：修复 OpenMP 循环条件
        const int totalYSteps = (sampling.effectiveHeight + sampling.rowStep - 1) / sampling.rowStep;
        const int totalXSteps = (sampling.effectiveWidth + sampling.colStep - 1) / sampling.colStep;
        const int totalSteps = std::min(totalYSteps * totalXSteps, maxSamples);
        
        // 使用简单的 parallel for 循环
        #pragma omp parallel for reduction(+:colorBuckets[:Params::COLOR_BUCKET_COUNT],validSamples)
        for (int step = 0; step < totalSteps; ++step) {
            int yIdx = step / totalXSteps;
            int xIdx = step % totalXSteps;
            
            int y = sampling.startY + yIdx * sampling.rowStep;
            int x = sampling.startX + xIdx * sampling.colStep;
            
            if (y >= maxY || x >= maxX) continue;
            
            uint8_t r, g, b;
            getPixelDirect(pixelData, x, y, width, bytesPerPixel, r, g, b);
            
            int bucketIndex = std::min(Params::COLOR_BUCKET_COUNT - 1, getColorBucket(r, g, b));
            colorBuckets[bucketIndex]++;
            validSamples++;
        }
    } else {
        // 串行版本
        for (int y = sampling.startY; y < maxY && validSamples < maxSamples; y += sampling.rowStep) {
            for (int x = sampling.startX; x < maxX && validSamples < maxSamples; x += sampling.colStep) {
                uint8_t r, g, b;
                getPixelDirect(pixelData, x, y, width, bytesPerPixel, r, g, b);
                
                int bucketIndex = std::min(Params::COLOR_BUCKET_COUNT - 1, getColorBucket(r, g, b));
                colorBuckets[bucketIndex]++;
                validSamples++;
            }
        }
    }
    
    if (validSamples == 0) return false;
    
    int nonEmptyBuckets = 0;
    int maxBucketCount = 0;
    
    for (int count : colorBuckets) {
        if (count > 0) {
            nonEmptyBuckets++;
            maxBucketCount = std::max(maxBucketCount, count);
        }
    }
    
        // 使用整数运算替代浮点
    int dominanceRatioPercent = (maxBucketCount * 100) / validSamples;
    
    OH_LOG_DEBUG(LOG_APP, "Frequency analysis: buckets=%{public}d, dominance=%{public}d%%", 
                nonEmptyBuckets, dominanceRatioPercent);
    
    bool hasText = nonEmptyBuckets >= Params::MIN_COLOR_BUCKETS && 
                   dominanceRatioPercent < Params::MAX_DOMINANCE_RATIO_PERCENT;
    
    return hasText;
}

bool TextLineDetector::hasTextLines(const uint8_t* pixelData, int width, int height, int bytesPerPixel, 
                                   const Rectangle& region) {
    if (!pixelData || width <= 0 || height <= 0 || bytesPerPixel <= 0) {
        OH_LOG_ERROR(LOG_APP, "Invalid parameters for text line detection");
        return false;
    }
    
    SamplingInfo sampling(width, height, region, false);
    
    if (sampling.effectiveWidth <= 0 || sampling.effectiveHeight <= 0) {
        OH_LOG_ERROR(LOG_APP, "Invalid effective region: width=%{public}d, height=%{public}d", 
                    sampling.effectiveWidth, sampling.effectiveHeight);
        return false;
    }
    
    OH_LOG_DEBUG(LOG_APP, "Text line detection: %{public}dx%{public}d, parallel=%{public}s", 
                sampling.effectiveWidth, sampling.effectiveHeight, 
                sampling.useParallel ? "true" : "false");
    
    std::vector<int> edgeProfile = extractEdgeProfileDirect(pixelData, width, height, bytesPerPixel, sampling);
    
    return analyzeTextLinePatternOptimized(edgeProfile, sampling);
}

bool TextLineDetector::hasTextContentByFrequency(const uint8_t* pixelData, int width, int height, int bytesPerPixel,
                                                 const Rectangle& region) {
    if (!pixelData || width <= 0 || height <= 0 || bytesPerPixel <= 0) {
        OH_LOG_ERROR(LOG_APP, "Invalid parameters for frequency analysis");
        return false;
    }
    
    SamplingInfo sampling(width, height, region, true);
    
    if (sampling.effectiveWidth <= 0 || sampling.effectiveHeight <= 0) {
        OH_LOG_ERROR(LOG_APP, "Invalid effective region for frequency: width=%{public}d, height=%{public}d", 
                    sampling.effectiveWidth, sampling.effectiveHeight);
        return false;
    }
    
    OH_LOG_DEBUG(LOG_APP, "Frequency analysis: %{public}dx%{public}d, parallel=%{public}s", 
                sampling.effectiveWidth, sampling.effectiveHeight,
                sampling.useParallel ? "true" : "false");
    
    return analyzeColorFrequencyDirect(pixelData, width, height, bytesPerPixel, sampling);
}

